package hexapawn.game;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import hexapawn.ai.MDPPlayer;
import hexapawn.ai.MiniMaxPlayer;
import hexapawn.io.UIOAction;
import hexapawn.io.UIOManager;
import hexapawn.io.UIOAction.UIOA_BEHAVIOR;
import hexapawn.main.Hexapawn;

/**
 * class Game - This is the object that contains the entire hexapawn game.
 * It will keep track of a Board object and two Player objects.
 * 
 * @author ChaoSXDemon
 *
 */
public class Game {
	
	private Hexapawn frame;
	private Board board;
	private Player p1, p2;
	private boolean turn = true;
	private UIOAction mouseAction;
	private Cell selectedCell = null;
	private List<Cell> possibleMoves;
	
	//Drawing constants
	private static int CELL_WIDTH;
	private static int CELL_HEIGHT;
	private static Point TOP_LEFT = new Point(100, 100);
	private static Point BOTTOM_RIGHT;
	private static int PAWN_WIDTH;
	private static int PAWN_HEIGHT;
	
	public Game(Hexapawn _frame, int row, int col){
		frame = _frame;
		BOTTOM_RIGHT = new Point(frame.getWidth() - TOP_LEFT.x, frame.getHeight() - TOP_LEFT.y);
		CELL_WIDTH = (BOTTOM_RIGHT.x - TOP_LEFT.x) / col;
		CELL_HEIGHT = (BOTTOM_RIGHT.y - TOP_LEFT.y) / row;
		PAWN_WIDTH = (int)(CELL_WIDTH - (CELL_WIDTH*0.2));
		PAWN_HEIGHT = (int)(CELL_HEIGHT - (CELL_HEIGHT*0.2));
		board = new Board(row, col);
		p1 = new TopPlayer(board);
		p2 = new BottomPlayer(board);
		board.setupPlayers(p1, p2);
		possibleMoves = new LinkedList<Cell>();
		mouseAction = new UIOAction("Mouse", UIOA_BEHAVIOR.INITIAL_PRESS_ONLY);
		frame.getManager().mapToMouse(mouseAction, UIOManager.MOUSE_BUTTON_1);	//setups the left click of a mouse
	}
	
	/**
	 * Returns the Cell object at the Mouse location
	 * 
	 * @return - The Cell at current mouse location. Returns null if the
	 * 			 location is invalid, meaning outside of the board.
	 */
	private Cell getCellAtMouse(){
		int mouseX = frame.getManager().getMouseX();
		int mouseY = frame.getManager().getMouseY();
		if(mouseX > TOP_LEFT.x && mouseX < BOTTOM_RIGHT.x){
			if(mouseY > TOP_LEFT.y && mouseY < BOTTOM_RIGHT.y){
				int row = (mouseY / CELL_HEIGHT) - 1;
				int col = (mouseX / CELL_WIDTH) - 1;
				if(row < 0) row = 0;
				if(col < 0) col = 0;
				if(row >= board.getRow()) row = board.getRow()-1;
				if(col >= board.getColumn()) col = board.getColumn()-1;
				return board.getCells()[row][col];
			}
		}
		return null;
	}
	
	private void drawPieces(Iterator<Piece> pieces, Graphics g, Color c){
		g.setColor(c);
		while(pieces.hasNext()){
			Piece p = pieces.next();
			g.fillRect((int)(TOP_LEFT.x+(p.getColumn()*CELL_WIDTH + CELL_WIDTH*0.1)), (int)(TOP_LEFT.y+(p.getRow()*CELL_HEIGHT + CELL_HEIGHT*0.1)), PAWN_WIDTH, PAWN_HEIGHT);
		}
	}
	
	private void drawPossibleMoves(Graphics g) {
		if(possibleMoves.size() == 0) return;
		Iterator<Cell> itr = possibleMoves.iterator();
		if(turn) g.setColor(Color.gray);
		else g.setColor(Color.gray);
		while(itr.hasNext()){
			Cell c = itr.next();
			g.fillRect(TOP_LEFT.x + c.getColumn()*CELL_WIDTH, TOP_LEFT.y + c.getRow()*CELL_HEIGHT, CELL_WIDTH, CELL_HEIGHT);
		}
	}
	
	public void update(){
		int winner = board.getWinner();
		switch(winner){
			case Player.PLAYER_1:
				System.out.println("Player 1 has won");
				break;
			case Player.PLAYER_2:
				System.out.println("Player 2 has won");
				break;
			case Player.PLAYER_MDP:
				break;
			case Player.PLAYER_MINIMAX:
				break;
			default:
				//System.out.println("No winner yet");
		}
		if(mouseAction.isPressed()) selectedCell = getCellAtMouse();
		if(selectedCell != null){
			if(turn){	//Player 1's turn
				if(selectedCell.hasPiece()){
					if(selectedCell.getPiece().getOwner() == Player.PLAYER_1)
						possibleMoves = p1.getPossibleMoves(selectedCell);
					else{
						if(possibleMoves.contains(selectedCell)){
							p1.makeMove(selectedCell);
							selectedCell = null;
							possibleMoves.clear();
							turn = !turn;
							board.switchTurn();
						}
					}
				}else{
					if(possibleMoves.contains(selectedCell)){
						p1.makeMove(selectedCell);
						selectedCell = null;
						possibleMoves.clear();
						turn = !turn;
						board.switchTurn();
					}
				}
			}else{	//Player 2's turn
				if(selectedCell.hasPiece()){
					if(selectedCell.getPiece().getOwner() == Player.PLAYER_2)
						possibleMoves = p2.getPossibleMoves(selectedCell);
					else{
						if(possibleMoves.contains(selectedCell)){
							p2.makeMove(selectedCell);
							selectedCell = null;
							possibleMoves.clear();
							turn = !turn;
							board.switchTurn();
						}
					}
				}else{
					if(possibleMoves.contains(selectedCell)){
						p2.makeMove(selectedCell);
						selectedCell = null;
						possibleMoves.clear();
						turn = !turn;
						board.switchTurn();
					}
				}
			}
		}
	}
	
	public void draw(Graphics g){
		g.setColor(Color.white);
		//Draw horizontal lines
		for(int i=0; i<=board.getRow(); i++){
			g.drawLine(TOP_LEFT.x, TOP_LEFT.y + (i*CELL_HEIGHT), BOTTOM_RIGHT.x, TOP_LEFT.y + (i*CELL_HEIGHT));
		}
		//Draw vertical lines
		for(int j=0; j<=board.getColumn(); j++){
			g.drawLine(TOP_LEFT.x + (j*CELL_WIDTH), TOP_LEFT.y, TOP_LEFT.x + (j*CELL_WIDTH), BOTTOM_RIGHT.y);
		}
		drawPossibleMoves(g);
		//Draw the pieces
		drawPieces(p1.getPieces().iterator(), g, Color.white);
		drawPieces(p2.getPieces().iterator(), g, Color.black);
	}

	public void resize(){
		BOTTOM_RIGHT = new Point(frame.getWidth() - TOP_LEFT.x, frame.getHeight() - TOP_LEFT.y);
		CELL_WIDTH = (BOTTOM_RIGHT.x - TOP_LEFT.x) / board.getColumn();
		CELL_HEIGHT = (BOTTOM_RIGHT.y - TOP_LEFT.y) / board.getRow();
		PAWN_WIDTH = (int)(CELL_WIDTH - (CELL_WIDTH*0.2));
		PAWN_HEIGHT = (int)(CELL_HEIGHT - (CELL_HEIGHT*0.2));
	}
	
	public void toTrainingMode(){
		p1 = new MDPPlayer(board);
		p2 = new MiniMaxPlayer(board);
	}
	
	public void toTestMode(){
		p1 = new MDPPlayer(board);
		p2 = new BottomPlayer(board);
	}

}
